#define WIN32_LEAN_AND_MEAN
#include <windows.h>

#include "GSemaphore.h"
#include "GError.h"

namespace GThread
{
	// Description: Creates the semaphore with given parameters
	// Return: True if successfull, false otherwise
	// Notes2: Initial count cannot be greater than maximum count
	// Notes3: Method fails if semaphore is created before
	// -----------------------------------------------------
	bool GSemaphore::Create(GUInt32 InitialCount, GUInt32 MaximumCount, const char* Name)
	{
		GUtil::GError::DebugCheck( InitialCount > MaximumCount, "InitialCount can not be greater than MaximumCount." );

		if (IsCreated())
		{
			return false;
		}

		Semaphore = CreateSemaphore(NULL, InitialCount, MaximumCount, Name);
		if (Semaphore == NULL)
		{
			GUtil::GError::Error(GUtil::GErrorMessageWin32(GetLastError()));
			return false;
		}

		this->Name = Name == NULL ? "" : Name;
		this->MaximumCount = MaximumCount;

		return true;
	}

	// Description: Releases the semaphore handle
	// Return:
	// Notes:
	// -----------------------------------------------------
	void GSemaphore::Release()
	{
		if (!IsCreated())
		{
			return;
		}
	
		Name = "";
		MaximumCount = 0;

		CloseHandle(Semaphore);
		Semaphore = NULL;
	}

	// Description: Increases the semaphore value by given parameter.
	// Return: Returns true if Free is successful, false otherwise.
	// Notes1: Semaphore must be created.
	// Notes2: If semaphore is signaled(value is zero) releasing it causes it to become unsignaled and available for other threads.
	// -----------------------------------------------------
	bool GSemaphore::Free(GUInt32 Count)
	{
		GUtil::GError::DebugCheck(!IsCreated(), "Semaphore is not created.");

		bool Result = ReleaseSemaphore(Semaphore, Count, NULL) == 0;
		if (Result)
		{
			GUtil::GError::Error(GUtil::GErrorMessageWin32(GetLastError()));
			return false;
		}

		return true;
	}
}